#pragma once

#include <iostream>
#include <pthread.h>
#include <functional>
#include "Sock.hpp"
#include "Protocol.hpp"

namespace tcpserver_ns{
    using namespace protocol_ns;

    using func_t = function<Response(const Request&)>;

    class TcpServer;
    class ThreadData{
    public:
        ThreadData(int sock, string ip, uint16_t port, TcpServer* tsvrp)
        : _sock(sock), _ip(ip), _port(port), _tsvrp(tsvrp){

        }

        ~ThreadData(){

        }

        int _sock;
        string _ip;
        uint16_t _port;
        TcpServer* _tsvrp;
    };

    class TcpServer{
    public:
        TcpServer(func_t func, uint16_t port): _func(func), _port(port){
            
        }

        void InitServer(){
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
            logMessage(Info, "init server done, listensock: %d", _listensock.GetSock());
        }

        void Start(){
            for(;;){
                string clientIp;
                uint16_t clientPort;
                int sock = _listensock.Accept(&clientIp, &clientPort);
                if(sock < 0)
                    continue;
                logMessage(Debug, "get a new client, client info: [%s : %d]", clientIp.c_str(), clientPort);


                pthread_t tid;
                ThreadData* td = new ThreadData(sock, clientIp, clientPort, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

        static void* ThreadRoutine(void* args){
            pthread_detach(pthread_self());
            ThreadData* td = static_cast<ThreadData*>(args);
            td->_tsvrp->ServiceIO(td->_sock, td->_ip, td->_port);
            logMessage(Debug, "thread quit, client quit...");
            delete td;
            return nullptr;
        }

        void ServiceIO(int sock, const string& ip, const uint16_t& port){
            string inbuffer;
            while(true){
                //0.保证拿到完整string报文
                string package;
                int n = ReadPackage(sock, inbuffer, &package);
                if(n == -1)
                    break;
                else if(n == 0)
                    continue;
                else{
                    //得到了完整string
                    //1.拿到有效载荷
                    package = RemoveHeader(package, n);

                    //2.反序列化
                    Request req;
                    req.Deserialize(package);

                    //3.提取用户请求的数据,并进行业务处理
                    Response res = _func(req);

                    //4.序列化
                    string send_string;
                    res.Serialize(&send_string);

                    //5.添加报头
                    send_string = AddHeader(send_string);

                    //6.给用户发送
                    send(sock, send_string.c_str(), send_string.size(), 0);
                }
            }
            close(sock);
        }

        ~TcpServer(){}

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };
}